import importlib
from typing import Dict, List, Union
from core.basic.mequment import get_equ
from core.basic.mequment import equipments
from core.basic.mskill import Skill, ActiveSkill, PassiveSkill
from .mroleinfo import CharacterEquipInfo
from .mproperty import 精通计算, 角色基础, CharacterInfo


class Character:
    # region 角色属性

    STR: float
    """力量"""

    INT: float
    """智力"""

    AtkP: float
    """物理攻击力"""

    AtkM: float
    """魔法攻击力"""

    PAtkP: float
    """物理攻击力增加%"""

    PAtkM: float
    """魔法攻击力增加%"""

    PDamage: float
    """伤害增加%"""

    PDamageC: float
    """暴击伤害增加%"""

    PSTR: float
    """力量增加%"""

    PINT: float
    """智力增加%"""

    PDamageB: float
    """附加伤害%"""

    PDamageBE: dict[str, float]
    """属性附加伤害%"""

    ElementA: dict[str, float]
    """属性攻击"""

    ElementDB: dict[str, float]
    """属性强化数值"""

    ElementR: dict[str, float]
    """属性抗性数值"""

    CriticalMP: float
    """魔法暴击率%"""

    CriticalM: float
    """魔法暴击"""

    CriticalPP: float
    """物理暴击率%"""

    CriticalP: float
    """物理暴击"""

    EquipmentSkillAttack: float
    """装备技能攻击力"""

    SkillAttack: float
    """技能内部攻击力"""

    SpeedA: float
    """攻击速度"""

    SpeedM: float
    """移动速度"""

    SpeedR: float
    """施放速度"""

    HitP: float
    """命中率"""

    Hit: float
    """命中"""

    Abnormal: dict[str, bool]
    """敌人异常状态"""

    MonsterInfo: dict[str, float]

    # endregion

    skills: List[Union[Skill, ActiveSkill, PassiveSkill]] = []
    """技能列表"""
    skillsWithName: Dict[str, Union[Skill, ActiveSkill, PassiveSkill]] = {}
    """技能名字对应技能"""
    equVersion: str = "0"
    """装备版本"""
    charEquipInfo: Dict[str, CharacterEquipInfo]
    """装备打造信息"""
    equs: equipments
    """装备列表"""

    # region 角色属性
    输出类型: str = "物理"

    buffer:bool = False
    # endregion

    def __init__(self, equVersion) -> None:
        self.equVersion = equVersion
        self.equs = get_equ(self.equVersion)
        self.STR = 0
        self.INT = 0
        self.AtkP = 0
        self.AtkM = 0
        self.PAtkP = 0
        self.PAtkM = 0
        self.PDamage = 0
        self.PDamageC = 0
        self.PSTR = 0
        self.PINT = 0
        self.PDamageB = 0
        self.ElementA = {
            "火": False,
            "冰": False,
            "光": False,
            "暗": False,
        }
        self.PDamageBE = {
            "火": 0,
            "冰": 0,
            "光": 0,
            "暗": 0,
        }
        self.ElementDB = {
            "火": 0,
            "冰": 0,
            "光": 0,
            "暗": 0,
        }
        self.ElementR = {
            "火": 0,
            "冰": 0,
            "光": 0,
            "暗": 0,
        }
        self.Abnormal = {
            "内伤": False,
            "灼伤": False,
            "感电": False,
            "创伤": False,
        }
        self.CriticalMP = 0
        self.CriticalM = 0
        self.CriticalPP = 0
        self.CriticalP = 0
        self.EquipmentSkillAttack = 1
        self.SkillAttack = 1
        self.SpeedA = 0
        self.SpeedM = 0
        self.SpeedR = 0
        self.HitP = 0
        self.Hit = 0
        self.MonsterInfo = {
            "DefenseP": 0,
            "DefenseM": 0,
            "火抗": 0,
            "冰抗": 0,
            "光抗": 0,
            "暗抗": 0,
        }
        pass

    # region 角色属性设置
    def SetBaseStatus(self) -> None:
        """设角色基础属性"""
        # 角色基础信息
        self.SetStatus(**角色基础.get(self.名称, {}))
        # 冒险团加成
        # todo 配置读取等级 目前20级
        self.SetStatus(力量=114, 智力=114)
        # 角色成就
        # todo 配置读取等级 目前6级
        self.SetStatus(力量=40, 智力=40)
        # 工会加成 满级计算
        # todo 配置读取等级 目前6级
        self.SetStatus(
            力量=32 + 20,
            智力=32 + 20,
            物暴=24,
            魔暴=24,
            物攻=24,
            魔攻=24,
            全属强=8,
            全属抗=8,
        )
        # 魔力结晶
        pass

    def SetStatus(
        self,
        力量=0,
        智力=0,
        力量P=0,
        智力P=0,
        物攻=0,
        魔攻=0,
        物攻P=0,
        魔攻P=0,
        黄字=0,
        白字=0,
        暴伤=0,
        技攻=0,
        技能技攻=0,
        全属强=0,
        火强=0,
        冰强=0,
        光强=0,
        暗强=0,
        全属抗=0,
        火抗=0,
        冰抗=0,
        光抗=0,
        暗抗=0,
        火属性攻击=False,
        冰属性攻击=False,
        光属性攻击=False,
        暗属性攻击=False,
        移速=0,
        攻速=0,
        施放=0,
        命中=0,
        命中率=0,
        物暴=0,
        物暴P=0,
        魔暴=0,
        魔暴P=0,
        **kwargs,
    ) -> None:
        """设置角色属性"""
        self.STR += 力量 + kwargs.get("STR", 0)
        self.INT += 智力 + kwargs.get("INT", 0)
        self.AtkP += 物攻 + kwargs.get("AtkP", 0)
        self.AtkM += 魔攻 + kwargs.get("AtkM", 0)
        self.PAtkP += 物攻P + kwargs.get("PAtkP", 0)
        self.PAtkM += 魔攻P + kwargs.get("PAtkM", 0)
        self.PDamage += 黄字 + kwargs.get("PDamage", 0)
        self.PDamageC += 暴伤 + kwargs.get("PDamageC", 0)
        self.PSTR += 力量P + kwargs.get("PSTR", 0)
        self.PINT += 智力P + kwargs.get("PINT", 0)
        self.PDamageB += 白字 + kwargs.get("PDamageB", 0)
        self.ElementA["火"] = (
            火属性攻击
            or kwargs.get("ElementA", {}).get("火", False)
            or self.ElementA["火"]
        )
        self.ElementA["冰"] = (
            冰属性攻击
            or kwargs.get("ElementA", {}).get("冰", False)
            or self.ElementA["冰"]
        )
        self.ElementA["光"] = (
            光属性攻击
            or kwargs.get("ElementA", {}).get("光", False)
            or self.ElementA["光"]
        )
        self.ElementA["暗"] = (
            暗属性攻击
            or kwargs.get("ElementA", {}).get("暗", False)
            or self.ElementA["暗"]
        )
        self.ElementDB["火"] += 火强 + kwargs.get("ElementDB", {}).get("火", 0) + 全属强
        self.ElementDB["冰"] += 冰强 + kwargs.get("ElementDB", {}).get("冰", 0) + 全属强
        self.ElementDB["光"] += 光强 + kwargs.get("ElementDB", {}).get("光", 0) + 全属强
        self.ElementDB["暗"] += 暗强 + kwargs.get("ElementDB", {}).get("暗", 0) + 全属强
        self.ElementR["火"] += 火抗 + kwargs.get("ElementR", {}).get("火", 0) + 全属抗
        self.ElementR["冰"] += 冰抗 + kwargs.get("ElementR", {}).get("冰", 0) + 全属抗
        self.ElementR["光"] += 光抗 + kwargs.get("ElementR", {}).get("光", 0) + 全属抗
        self.ElementR["暗"] += 暗抗 + kwargs.get("ElementR", {}).get("暗", 0) + 全属抗
        self.CriticalMP += kwargs.get("CriticalMP", 0) + 魔暴P
        self.CriticalM += kwargs.get("CriticalM", 0) + 魔暴
        self.CriticalPP += kwargs.get("CriticalPP", 0) + 物暴P
        self.CriticalP += kwargs.get("CriticalP", 0) + 物暴
        self.EquipmentSkillAttack *= (1 + 技攻) * (1 + kwargs.get("EquipmentSkillAttack", 0))
        self.SkillAttack += 技能技攻 + kwargs.get("SkillAttack", 0)
        self.SpeedA += 攻速 + kwargs.get("SpeedA", 0)
        self.SpeedM += 移速 + kwargs.get("SpeedM", 0)
        self.SpeedR += 施放 + kwargs.get("SpeedR", 0)
        self.HitP += 命中率 + kwargs.get("HitP", 0)
        self.Hit += 命中 + kwargs.get("Hit", 0)
        pass

    def AddSkillLv(self, min, max, lv, type=-1) -> None:
        """
        增加技能等级
        type: -1 全部, 0 被动, 1 主动
        """
        for skill in self.skills:
            if min <= skill.requiredLv <= max:
                if type == -1 or skill.type == type:
                    skill.AddLv(lv, self)

    def SetSkillCD(self, min=1, max=99, cd=0) -> None:
        """
        设置技能CD
        type: -1 全部, 0 被动, 1 主动
        """
        for skill in self.skills:
            if min <= skill.requiredLv <= max and skill.damage:
                skill.CDR *= 1 - cd

    def GetSkillByName(self, name) -> Union[Skill, ActiveSkill, PassiveSkill]:
        """通过技能名获取技能"""
        id = self.skillsWithName.get(name, -1)
        if id < 0:
            return Skill()
        return self.skills[id]

    # endregion

    # region 计算相关
    def SetDetail(self, info: Dict[str, dict]) -> None:
        self.charEquipInfo = {}
        """打造信息导入"""
        for key in info["equips"]:
            temp = CharacterEquipInfo(info["equips"][key])
            self.charEquipInfo[key] = temp

    # def calc(self):
    #     """计算角色属性"""
    #     func = []
    #     for i in self.charEquipInfo:
    #         # 计算装备
    #         temp = self.equs.get_func_by_id(self.charEquipInfo[i].id)
    #         func.append(temp)
    #         temp(self)
    #     pass

    def getInfo(self):
        """返回到前端信息"""
        info = {}
        info["alter"] = self.实际名称
        info["equVersion"] = self.equVersion
        info["name"] = self.名称
        info["weaopns"] = self.武器选项
        skillInfo = []
        for skill in self.skills:
            skillInfo.append(
                {
                    "name": skill.name,
                    "icon": skill.icon,
                    "type": skill.type,
                    "SPCost": skill.SPCost,
                    "maxLv": skill.lv,
                    # "requiredLv": skill.requiredLv,
                    # "masterLv": skill.masterLv,
                    "TPCost": 0 if not skill.hasTP else skill.TPCost,
                    # "masterTPLv":0 if not skill.hasTP else  skill.masterTPLv,
                    "maxTPLv":0 if not skill.hasTP else  skill.TPLearnMax,
                }
            )
        info["skills"] = skillInfo
        equs = []
        enchats = []
        emblems = []
        # 装备过滤
        for i in self.equs.info:
            if (i.typeSon1Id == "武器" and i.typeSon2Id not in self.武器选项) or (
                i.name.startswith("精 · ") and self.异界 not in i.name
            ):
                pass
            else:
                equs.append({
                    "id" : i.id,
                    "name" : i.name,
                    "icon" : i.icon,
                    "typeSon1Id" : i.typeSon1Id,
                    "typeSon2Id" : i.typeSon2Id,
                    "typeSon3Id" : i.typeSon3Id,
                    "rarity" : i.rarity,
                    "lv" : i.lv,
                    "suit" : i.suit,
                })
        # 附魔、徽章
        for i in self.equs.prop:
            if i.typeSon1Id == "附魔":
                enchats.append({
                    "id" : i.id,
                    "name" : i.name,
                    "icon" : i.icon,
                    "typeSon1Id" : i.typeSon1Id,
                    "typeSon2Id" : i.typeSon2Id,
                    "typeSon3Id" : i.typeSon3Id,
                    "rarity" : i.rarity,
                    "lv" : i.lv,
                    "desc" : i.desc,
                })
            if i.typeSon1Id == "徽章":
                emblems.append({
                    "id" : i.id,
                    "name" : i.name,
                    "icon" : i.icon,
                    "typeSon1Id" : i.typeSon1Id,
                    "typeSon2Id" : i.typeSon2Id,
                    "typeSon3Id" : i.typeSon3Id,
                    "rarity" : i.rarity,
                    "lv" : i.lv,
                    "desc" : i.desc,
                })
        info["equips"] = equs
        info["enchats"] = enchats
        info["emblems"] = emblems
        info["seal"] = [i.__dict__ for i in self.equs.seal]
        return info

    def getBasicInos(self):
        res = []
        attrs = []
        if self.输出类型 == "物理":
            attrs = ["STR", "PSTR", "AtkP", "PAtkP", "CriticalPP", "CriticalP"]
        if self.输出类型 == "魔法":
            attrs = ["INT", "PINT", "AtkM", "PAtkM", "CriticalMP", "CriticalM"]
        for attr in attrs + ["PDamage", "PDamageC", "PDamageB", "SpeedA", "SpeedM","SpeedR"]:
            temp = getattr(CharacterInfo, attr)
            res.append(
                {
                    "name": temp.name,
                    "value": temp.value(getattr(self, attr)),
                    "icon": temp.icon,
                }
            )
        keys = ["火", "冰", "光", "暗"]
        for index in range(0,4):
            temp = getattr(CharacterInfo, f"ElementDB{index}")
            res.append(
                {
                    "name": temp.name,
                    "value": temp.value(getattr(self, "ElementDB")[keys[index]]),
                    "icon": temp.icon,
                }
            )
            temp = getattr(CharacterInfo, f"ElementR{index}")
            res.append(
                {
                    "name": temp.name,
                    "value": temp.value(getattr(self, "ElementR")[keys[index]]),
                    "icon": temp.icon,
                }
            )
        return res

    def calc(self, setInfo: Dict[str, dict]):
        funcs = []
        suits = []
        self.SetDetail(setInfo)
        self.SetBaseStatus()
        for skill in self.skills:
            skill.effect(self)
        for i in self.charEquipInfo:
            # region 装备效果
            fun = self.equs.get_func_by_id(f"equ_{self.charEquipInfo[i].id}")
            equ = self.equs.get_equ_by_id(self.charEquipInfo[i].id)
            if equ is None:
                continue
            self.SetStatus(**equ.__dict__)
            funcs.append(fun + (equ,))
            # 护甲精通计算
            if equ.typeSon2Id == self.防具类型:
                self.SetStatus(**精通计算(equ.lv,equ.rarity,equ.typeSon1Id,equ.typeSon2Id,self.输出类型,self.buffer))
            # 套装效果
            suits += (equ.suit or "").split(",")
            # endregion
            # region 附魔效果
            fun = self.equs.get_func_by_id(f"prop_{self.charEquipInfo[i].enchant}")
            funcs.append(fun + (equ,))
            # endregion
            # region 徽章效果
            for emblem in self.charEquipInfo[i].emblems:
                fun = self.equs.get_func_by_id(f"prop_{emblem}")
                funcs.append(fun + (equ,))
            # endregion
            # region 魔法封印效果
            for seal in self.charEquipInfo[i].seals:
                fun = self.equs.get_func_by_id(f"seal_{seal}")
                funcs.append(fun + (equ,))
            # endregion
        # region 套装效果
        matchSuit = []
        for i in list(set(filter(lambda x: x != "" and x is not None, suits))):
            # 获取当前的套装的数量
            nums = len(list(filter(lambda x: x == i, suits)))
            # 获取当前的套装信息
            suisInfos = list(filter(lambda x: x.suitID == i, self.equs.suit))
            if len(suisInfos) > 0:
                matchSuit += [
                    i.id for i in list(filter(lambda x: x.needNum <= nums, suisInfos))
                ]
                # 兼容于判断
                if (
                    suisInfos[0].compatibility is not None
                    and suisInfos[0].compatibility != ""
                ):
                    for compatibility in suisInfos[0].compatibility.split(","):
                        # 兼容于的装备数量
                        numsComp = len(
                            list(filter(lambda x: x == compatibility, suits))
                        )
                        # 大于兼容于小于兼容于加上当前套装数量
                        if numsComp > 0:
                            matchSuit += [
                                i.id
                                for i in list(
                                    filter(
                                        lambda x: x.suitID == compatibility
                                        and numsComp < x.needNum <= nums + numsComp,
                                        self.equs.suit,
                                    )
                                )
                            ]
        for i in matchSuit:
            fun = self.equs.get_func_by_id(f"suit_{i}")
            funcs.append(fun + (None,))
        # endregion
        funcs.sort(key=lambda x: x[2])
        for func in funcs:
            # 站街
            func[1](self, func[3], 0)
            # 进图
            func[1](self, func[3], 1)
        return {
            "basicInfo": self.getBasicInos(),
            "skillInfo": [],
        }

    # endregion


def createCharacter(alter: str, equVersion: str = "0"):
    character: Character = None
    module_name = "core.characters." + alter
    try:
        character = importlib.import_module(module_name).classChange(equVersion)
    except Exception as ex:
        print(ex)
        print("create character " + module_name + " error.")
        pass
    return character
